;;; +program.el --- configuration -*- lexical-binding: t -*-

;;; Commentary:

;;; Code:

;; -------- update prog-mode config --------

;; (add-hook 'prog-mode-hook
;; 	      (lambda ()
;;             ;; automatically inserts the corresponding closing parenthesis,
;;             ;; (when typing open parenthesis) and vice versa.
;;             (electric-pair-mode +1)
;;             ;; (prettify-symbols-mode +1) ;; display some symbols more pretty.
;;             ;; Use large font for function name when programming.
;;             ;; (face-remap-add-relative 'font-lock-function-name-face :height 150)
;;             ))

;; --------  keeps code always indented --------
(use-package aggressive-indent
  :defer t
  :diminish
  :hook
  ((after-init . global-aggressive-indent-mode)
   (find-file . (lambda ()
                  (when (or (> (buffer-size) 500000)
                            (and (fboundp 'buffer-line-statistics)
                                 (> (car (buffer-line-statistics)) 10000)))
                    (aggressive-indent-mode -1)))))
  :config
  ;; Disable in some modes
  (dolist (mode '(gitconfig-mode
                  artist-mode asm-mode
                  web-mode html-mode css-mode css-ts-mode
                  go-mode go-ts-mode
                  python-ts-mode yaml-ts-mode
                  separedit-mode scala-mode
                  shell-mode term-mode vterm-mode
                  prolog-inferior-mode))
    (add-to-list 'aggressive-indent-excluded-modes mode))

  ;; Disable in some commands
  (add-to-list 'aggressive-indent-protected-commands #'delete-trailing-whitespace t)

  ;; Be slightly less aggressive in C/C++/C#/Java/Go/Swift
  (add-to-list 'aggressive-indent-dont-indent-if
               '(and (derived-mode-p 'c-mode 'c++-mode 'csharp-mode
                                     'java-mode 'go-mode 'swift-mode)
                     (null (string-match
                            "\\([;{}]\\|\\b\\(if\\|for\\|while\\)\\b\\)"
                            (thing-at-point 'line))))))

;; -------- A universal syntax checker --------
(use-package flymake
  :diminish
  :functions my-elisp-flymake-byte-compile
  :bind
  ("C-c F" . flymake-show-buffer-diagnostics)
  :hook
  (prog-mode . flymake-mode)
  :init
  (setq flymake-no-changes-timeout nil
        flymake-fringe-indicator-position 'left-fringe)
  :config
  ;; Check elisp with `load-path'
  (defun my-elisp-flymake-byte-compile (fn &rest args)
    "Wrapper for `elisp-flymake-byte-compile'."
    (let ((elisp-flymake-byte-compile-load-path
           (append elisp-flymake-byte-compile-load-path load-path)))
      (apply fn args)))
  (advice-add 'elisp-flymake-byte-compile :around #'my-elisp-flymake-byte-compile))

;; Flymake diagnostics on cursor hover
(use-package flymake-popon
  :diminish
  :custom-face
  (flymake-popon ((t :inherit default :height 0.85)))
  :init
  (setq flymake-popon-width 80)
  :hook
  (flymake-mode . flymake-popon-mode))

;; -------- symbol-overlay --------
(use-package symbol-overlay
  :defer t
  :diminish
  :hook
  (prog-mode . symbol-overlay-mode)
  :config
  (defhydra hydra-symbol-overlay ()
    ("i" symbol-overlay-put "標/否" :column "標記")
    ("D" symbol-overlay-remove-all "移除所有")
    ("n" symbol-overlay-jump-next "下一個" :column "跳轉")
    ("p" symbol-overlay-jump-prev "上一個")
    ("r" symbol-overlay-rename "重命名" :column "操作"))
  :bind
  (("M-i" . 'hydra-symbol-overlay/body)
   ("M-n" . 'symbol-overlay-jump-next)
   ("M-p" . 'symbol-overlay-jump-prev)))

(provide '+program)

;;; +program.el ends here
